package com.ywcq.netty.httpserver.helloworld;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.AdaptiveRecvByteBufAllocator;
import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultMessageSizeEstimator;
import io.netty.channel.EventLoop;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.AsciiString;
import static io.netty.handler.codec.http.HttpResponseStatus.*;
import static io.netty.handler.codec.http.HttpVersion.*;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class HttpHelloWorldServerHandler extends ChannelInboundHandlerAdapter 
{
    private static final byte[] CONTENT = { 'H', 'e', 'l', 'l', 'o', ' ', 'N', 'e', 't','t', 'y' };
    private static final byte[] CONTENT_FOR_404 = {'4','0','4'};

    private static final AsciiString CONTENT_TYPE = new AsciiString("Content-Type");
    private static final AsciiString CONTENT_LENGTH = new AsciiString("Content-Length");
    private static final AsciiString CONNECTION = new AsciiString("Connection");
    private static final AsciiString KEEP_ALIVE = new AsciiString("keep-alive");
    private static final AsciiString LAST_MODIFIED = new AsciiString("Last-Modified");
    
    Logger logger = LogManager.getLogger();
    
    StaticContentCache cache = new StaticContentCache();

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
    	EventLoop eventLoop = ctx.channel().eventLoop();
    	logger.info(eventLoop.getClass().getName());
        if (msg instanceof HttpRequest) {
            HttpRequest req = (HttpRequest) msg;
            String uri = req.uri();
            logger.info("request method:" + req.method());
            logger.info("request protocolVersion:" + req.protocolVersion());
            logger.info("request headers:" + req.headers());
            boolean keepAlive = HttpUtil.isKeepAlive(req);
            DefaultFullHttpResponse response = null;
            logger.info("request uri:" + uri);
            ByteBuf content = null;
            HttpResponseStatus status = OK;
            if ("/favicon.ico".equals(uri))
            {
            	content = Unpooled.wrappedBuffer(CONTENT_FOR_404);
            	status = NOT_FOUND;
            }
            else if (uri.startsWith("/static/"))
            {
            	//静态资源
            	String resourceName = uri.substring(uri.lastIndexOf("/") + 1);
            	if (!isResourceModifyed(req,resourceName))
            	{
            		status = NOT_MODIFIED;
            	}
            	StaticResource resource = cache.getResourceContent(resourceName);
            	if (null != resource)
            	{
            		content = Unpooled.wrappedBuffer(cache.getResourceContent(resourceName).getContent());
                	response = new DefaultFullHttpResponse(HTTP_1_1, status, content);
                	
//                	Content-Length:20214
//                	Content-Type:image/png;charset=UTF-8
//                	Date:Tue, 27 Jun 2017 09:23:30 GMT
//                	Last-Modified:Mon, 12 Dec 2016 13:10:10 GMT
                	String modifyTime = resource.getLastModifyDate().toString();
                	response.headers().set(CONTENT_TYPE, "image/png");
                	response.headers().set(LAST_MODIFIED, modifyTime);
            	}
            	else
            	{
            		status = NOT_FOUND;
            		response = new DefaultFullHttpResponse(HTTP_1_1, status, null);
            	}
            	
            }else
            {
            	content = Unpooled.wrappedBuffer(CONTENT);
            	response = new DefaultFullHttpResponse(HTTP_1_1, status, content);
            	response.headers().set(CONTENT_TYPE, "text/plain");
            }
            response.headers().setInt(CONTENT_LENGTH, response.content().readableBytes());
            if (!keepAlive) {
                ctx.write(response).addListener(ChannelFutureListener.CLOSE);
            } else {
            	response.headers().set(CONNECTION, KEEP_ALIVE);
                ctx.write(response);
            }
        }
    }

    private boolean isResourceModifyed(HttpRequest req,String resourceName) 
    {
//    	If-Modified-Since:Mon, 12 Dec 2016 13:10:10 GMT
    	String modifyDate = req.headers().get("If-Modified-Since");
    	if (null == modifyDate || "".equals(modifyDate.trim()))
    	{
    		return true;//第一次请求资源
    	}
		return false;
	}

	@Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}
